﻿/************************************************************************

 This file is part of "10 Second Tim".

 "10 Second Tim" is free software: you can redistribute it and/or modify
 it under the terms of the GNU General Public License as published by
 the Free Software Foundation, either version 3 of the License, or
 (at your option) any later version.

 "10 Second Tim" is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 GNU General Public License for more details.

 You should have received a copy of the GNU General Public License
 along with "10 Second Tim".  If not, see <http://www.gnu.org/licenses/>.

************************************************************************/

// All code (c)2013 Scott Bevin. all rights reserved

using System.Collections.Generic;
using Microsoft.Xna.Framework.Graphics;

namespace LDE
{
	public class GameScreenManager
	{
		private GameMain Game = null;
		private SpriteBatch SpriteBatch = null;

		public List<GameScreen> GameScreens = new List<GameScreen>( );

		public struct AddGameScreenData
		{
			public GameScreen GameScreen;
			public GameScreen Ref;

			public enum PositioningOptions
			{
				OnTop,
				OnBottom,
				AboveRef,
				BelowRef,
			}

			public PositioningOptions Positioning;
		}

		private List<AddGameScreenData> GameScreensToAdd = new List<AddGameScreenData>( );

		public GameScreenManager( GameMain game )
		{
			Game = game;
			SpriteBatch = new SpriteBatch( game.GraphicsDevice );
		}

		public void AddGameScreen( GameScreen screen, GameScreen Ref, AddGameScreenData.PositioningOptions positioning )
		{
			screen.Setup( this, Game );

			AddGameScreenData agds = new AddGameScreenData( );
			agds.GameScreen = screen;
			agds.Ref = Ref;
			agds.Positioning = positioning;

			GameScreensToAdd.Add( agds );
		}

		public void Update( float dt )
		{
			while ( GameScreensToAdd.Count > 0 )
			{
				List<AddGameScreenData> addScreens = new List<AddGameScreenData>( GameScreensToAdd );
				GameScreensToAdd.Clear( );

				foreach ( AddGameScreenData gs in addScreens )
				{
					Player.Get.PushOwner( gs.GameScreen );
					gs.GameScreen.OnAdded( );

					if ( gs.Positioning == AddGameScreenData.PositioningOptions.OnBottom )
					{
						GameScreens.Insert( 0, gs.GameScreen );
					}
					else if ( gs.Positioning == AddGameScreenData.PositioningOptions.OnTop || gs.Ref == null )
					{
						GameScreens.Add( gs.GameScreen );
					}
					else if ( gs.Positioning == AddGameScreenData.PositioningOptions.AboveRef )
					{
						bool found = false;

						for ( int i = 0; i < GameScreens.Count; ++i )
						{
							if ( GameScreens[ i ] == gs.Ref )
							{
								found = true;
								GameScreens.Insert( i + 1, gs.GameScreen );

								break;
							}
						}

						if ( !found )
							GameScreens.Add( gs.GameScreen );
					}
					else if ( gs.Positioning == AddGameScreenData.PositioningOptions.BelowRef )
					{
						bool found = false;

						for ( int i = 0; i < GameScreens.Count; ++i )
						{
							if ( GameScreens[ i ] == gs.Ref )
							{
								found = true;
								GameScreens.Insert( i, gs.GameScreen );

								break;
							}
						}

						if ( !found )
							GameScreens.Add( gs.GameScreen );
					}
				}
			}

			List<GameScreen> GameScreensToRemove = new List<GameScreen>( );

			for ( int i = 0; i < GameScreens.Count; ++i )
			{
				GameScreens[ i ].Update( dt );

				if ( GameScreens[ i ].KillScreen )
					GameScreensToRemove.Add( GameScreens[ i ] );
			}

			foreach ( GameScreen gs in GameScreensToRemove )
			{
				gs.OnRemoved( );
				Player.Get.PopOwner( gs );
				GameScreens.Remove( gs );
			}

#if DEBUG
			DebugDraw.Get.AddText( "GameScreens:" );
			foreach ( GameScreen gs in GameScreens )
				DebugDraw.Get.AddText( " - " + gs.ToString( ) );
#endif
		}

		public void Render( float dt, GraphicsDevice gd )
		{
			for ( int i = GameScreens.Count - 1; i >= 0; --i )
			{
				if ( GameScreens[ i ].Fullscreen )
				{
					for ( int j = 0; j < GameScreens.Count; ++j )
					{
						GameScreens[ j ].Render( dt, gd, SpriteBatch );
					}
				}
			}
		}
	}
}